﻿using System;
using System.Linq;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;

using Expertime.Multitude.Intranet.Utils;
using Expertime.Multitude.Intranet.Security;
using Microsoft.SharePoint.Linq;
using System.Collections.Generic;
using System.Configuration;
using System.Text;

namespace Expertime.Multitude.Intranet.EventReceivers.DemandeActionReceiver
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class DemandeActionReceiver : SPItemEventReceiver
    {

        #region Properties
        public bool SendMails
        {
            get
            {
                bool sendMails = true;
                if (ConfigurationManager.AppSettings.AllKeys.Any(k => k == "expertime_sendmails"))
                   bool.TryParse(ConfigurationManager.AppSettings["expertime_sendmails"], out sendMails);
                return sendMails;
            }
        }
        public bool OverrideSecurity
        {
            get
            {
                bool overrideSecurity = true;
                if (ConfigurationManager.AppSettings.AllKeys.Any(k => k == "expertime_overridesecurity"))
                    bool.TryParse(ConfigurationManager.AppSettings["expertime_overridesecurity"], out overrideSecurity);
                return overrideSecurity;
            }
        }
        #endregion

        /// <summary>
        /// An item is being added.
        /// </summary>
        public override void ItemAdding(SPItemEventProperties properties)
        {
            base.ItemAdding(properties);

            using (var currentSite = new SPSite(properties.WebUrl))
            {
                bool allowUnsafeUpdatesOldValue = currentSite.AllowUnsafeUpdates;
                currentSite.AllowUnsafeUpdates = true;
                using (var currentWeb = currentSite.OpenWeb())
                {
                    try
                    {
                        // A l'ajout d'une demande, on alerte par mail le responsable du processus concerné
                        if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_DEMANDES, StringComparison.InvariantCultureIgnoreCase))
                        {
                            string demandeTitle = (string)(properties.AfterProperties[SPListItemPlanActionUtility.FIELD_TITLE] ?? String.Empty);

                            string processusFieldValue = (string)(properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PROCESSUS] ?? String.Empty);
                            SPFieldLookupValue processusLookupValue = new SPFieldLookupValue(processusFieldValue);
                            ProcessusÉlément processus = SPListItemPlanActionUtility.GetProcessusByID(properties.WebUrl,
                                                                                                      processusLookupValue.
                                                                                                          LookupId);

                            if (processus != null && processus.PiloteID.HasValue)
                            {
                                SPFieldUserValue responsableField = null;
                                // - 1 - notification par mail au responsable du processus
                                try
                                {
                                    responsableField = new SPFieldUserValue(currentWeb, processus.PiloteID.Value, processus.PiloteImnName);

                                    if (SendMails)
                                    {
                                        bool hasEmail = (responsableField.User != null && !string.IsNullOrEmpty(responsableField.User.Email));

                                        bool emailSended = hasEmail && SendNotificationOuvertureDemande(properties.Web, "[DemandeActionReceiver][ItemAdding]",
                                                                                            responsableField.User, demandeTitle);
                                        if (emailSended)
                                            properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_INFORMATIONS] =
                                                string.Format("Notification mail envoyée à: {0}.", processus.PiloteImnName);
                                        else
                                            properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_INFORMATIONS] =
                                                string.Format("Problème: Notification mail non envoyée à {0}.",
                                                              processus.PiloteImnName);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, "[DemandeActionReceiver][ItemAdding] Erreur lors de la notification mail.");
                                }
                                // - 2 - Init values:
                                try
                                {
                                    properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_RESPONSABLE] = responsableField;
                                    properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT] = "1- A traiter";
                                    properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS] = null;
                                    properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_CLOTURE] = null;
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, "[DemandeActionReceiver][ItemAdding] Erreur lors de l'initialisation des valeurs.");
                                }

                            }
                            else
                                LogManager.LogDebug("[DemandeActionReceiver][ItemAdding]",
                                                    "Processus.PiloteImnName IsNullOrEmpty.");

                        }
                        // A l'ajout d'un plan d'actions, on affecte le responsable du processus concerné
                        else if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_PLANS_ACTIONS,
                                                        StringComparison.InvariantCultureIgnoreCase))
                        {
                            string processusFieldValue = (string)(properties.AfterProperties[SPListItemPlanActionUtility.FIELD_PLANS_PROCESSUS] ?? String.Empty);
                            SPFieldLookupValue processusLookupValue = new SPFieldLookupValue(processusFieldValue);
                            ProcessusÉlément processus = SPListItemPlanActionUtility.GetProcessusByID(properties.WebUrl,
                                                                                                      processusLookupValue.
                                                                                                          LookupId);

                            if (processus != null && processus.PiloteID.HasValue)
                            {
                                SPFieldUserValue responsableField = null;
                                // - 1 - notification par mail au responsable du processus
                                try
                                {
                                    responsableField = new SPFieldUserValue(currentWeb, processus.PiloteID.Value, processus.PiloteImnName);
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, "[DemandeActionReceiver][ItemAdding] Erreur lors de la récupération du responsable du processus.");
                                }
                                // - 2 - Init values:
                                try
                                {
                                    properties.AfterProperties[SPListItemPlanActionUtility.FIELD_PLANS_RESPONSABLE] = responsableField;
                                    properties.AfterProperties[SPListItemPlanActionUtility.FIELD_PLANS_RESPONSABLE_PROCESSUS] = responsableField;
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, "[DemandeActionReceiver][ItemAdding] Erreur lors de l'initialisation des valeurs.");
                                }

                            }
                            else
                                LogManager.LogDebug("[DemandeActionReceiver][ItemAdding]",
                                                    "Processus.PiloteImnName IsNullOrEmpty.");

                        }
                        // Test non fonctionnel:
                        //// A l'ajout d'une action
                        //else if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_ACTIONS, StringComparison.InvariantCultureIgnoreCase))
                        //{
                        //    try
                        //    {
                        //        if (properties.AfterProperties[SPListItemPlanActionUtility.FIELD_ACTIONS_CONTENU_ASSOCIE] != null)
                        //        {
                        //            LogManager.LogDebug("[ActionReceiver][ItemAdding]", string.Format("Contenu Associé = {0}.", properties.AfterProperties[SPListItemPlanActionUtility.FIELD_ACTIONS_CONTENU_ASSOCIE]));
                        //            properties.AfterProperties[SPListItemPlanActionUtility.FIELD_ACTIONS_PLAN_ACTIONS] =
                        //                new SPFieldLookupValue(
                        //                    properties.AfterProperties[
                        //                        SPListItemPlanActionUtility.FIELD_ACTIONS_CONTENU_ASSOCIE].ToString());
                        //        }
                        //    }
                        //    catch (Exception ex)
                        //    {
                        //        LogManager.LogException(ex, "[ActionReceiver][ItemAdding] Erreur lors de la récupération du contenu associé à l'action.");
                        //    }
                        //}
                        
                    }
                    catch (Exception ex)
                    {
                        LogManager.LogException(ex, string.Format("[DemandeActionReceiver][ItemAdding] Erreur non gérée sur l'ajout d'un item de la liste '{0}'", properties.ListTitle));
                    }
                }//end using web
            }//end using site
        }

        /// <summary>
        /// An item was added
        /// </summary>
        public override void ItemAdded(SPItemEventProperties properties)
        {
            base.ItemAdded(properties);

            try
            {
                // A l'ajout d'une demande, on alerte par mail le responsable du processus concerné
                if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_DEMANDES,
                                                StringComparison.InvariantCultureIgnoreCase))
                {
                    if (OverrideSecurity)
                        ApplySecurityOnDemande("[DemandeActionReceiver][ItemAdded]", properties);
                }
                else if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_PLANS_ACTIONS, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (OverrideSecurity)
                        ApplySecurityOnPlanActions("[PlanActionsReceiver][ItemAdded]", properties);
                }
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("[DemandeActionReceiver][ItemAdded] Erreur non gérée sur l'ajout d'un item de la liste '{0}'", properties.ListTitle));
            }
        }

        /// <summary>
        /// An item is being updated
        /// </summary>
        public override void ItemUpdating(SPItemEventProperties properties)
        {
            base.ItemUpdating(properties);

            //try
            //{
            //    LogManager.LogDebug("[DemandeActionReceiver][ItemUpdating]", string.Format("Liste={0}.", properties.ListTitle));
            //    if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_DEMANDES, StringComparison.InvariantCultureIgnoreCase))
            //    {
            //        bool stateChanged = (properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT] != properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT]);
            //        bool planActionChanged = (properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS] != properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS]);

            //        LogManager.LogDebug("[DemandeActionReceiver][ItemUpdating]", string.Format("StateChanged[{0}->{1}]:{2}, PlanActionChanged=[{3}->{4}]:{5}", new object[]{
            //            properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT],
            //            properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT],
            //            stateChanged, 
            //            properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS],
            //            properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS],
            //            planActionChanged                                                                                                                    
            //        }));


            //    }//endif LIST_DEMANDES
            //}
            //catch (Exception ex)
            //{
            //    LogManager.LogException(ex, string.Format("[DemandeActionReceiver][ItemUpdating] Erreur non gérée sur l'ajout d'un item de la liste '{0}'", properties.ListTitle));
            //}
        }

        /// <summary>
        /// An item was updated
        /// </summary>
        public override void ItemUpdated(SPItemEventProperties properties)
        {
            base.ItemUpdated(properties);

            if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_DEMANDES, StringComparison.InvariantCultureIgnoreCase))
            {
                OnDemandeUpdated(properties);
                if (OverrideSecurity)
                    ApplySecurityOnDemande("[DemandeActionReceiver][ItemUpdated]", properties);
            }
            else if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_ACTIONS, StringComparison.InvariantCultureIgnoreCase))
            {
                OnActionUpdated(properties);
            }
            else if (properties.ListTitle.Equals(SPListItemPlanActionUtility.LIST_PLANS_ACTIONS, StringComparison.InvariantCultureIgnoreCase))
            {
                OnPlanActionUpdated(properties);
                if (OverrideSecurity)
                    ApplySecurityOnPlanActions("[PlanActionsReceiver][ItemUpdated]", properties);
            }
        }

        #region Methods Mail
        public static bool SendNotificationOuvertureDemande(SPWeb currentWeb, string traceContext, SPUser user, string demandeTitle)
        {
            bool emailSended = false;
            string userLogin = string.Empty;
            try
            {
                userLogin = user.LoginName;
                string userMail = user.Email;//UserUtils.GetSPUSerEmail(userLogin);
                if (!string.IsNullOrEmpty(userMail))
                {
                    emailSended = Emails.EmailUtils.SendMailNotificationDemande(currentWeb, userMail,
                                                                                     demandeTitle);

                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail sended to {0} = {1}.", userMail, emailSended));
                }
                else
                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail({0}) IsNullOrEmpty.",
                                                      userLogin));
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("{0} Erreur lors de la notification de la demande '{1}' par email au user '{2}'.", traceContext, demandeTitle, userLogin));
            }
            return emailSended;
        }
        public static bool SendNotificationClotureDemande(SPWeb currentWeb, string traceContext, SPUser user, string demandeTitle, string demandeEtat)
        {
            bool emailSended = false;
            string userLogin = string.Empty;
            try
            {
                userLogin = user.LoginName;
                string userMail = user.Email;//UserUtils.GetSPUSerEmail(userLogin);
                if (!string.IsNullOrEmpty(userMail))
                {
                    emailSended = Emails.EmailUtils.SendMailClotureDemande(currentWeb, userMail, demandeTitle, demandeEtat);

                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail sended to {0} = {1}.", userMail, emailSended));
                }
                else
                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail({0}) IsNullOrEmpty.",
                                                      userLogin));
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("{0} Erreur lors de la notification de cloture de la demande '{1}' par email au user '{2}'.", traceContext, demandeTitle, userLogin));
            }
            return emailSended;
        }
        public static bool SendNotificationTraitementDemande(SPWeb currentWeb, string traceContext, SPUser user, string demandeTitle)
        {
            bool emailSended = false;
            string userLogin = string.Empty;
            try
            {
                userLogin = user.LoginName;
                string userMail = user.Email;//UserUtils.GetSPUSerEmail(userLogin);
                if (!string.IsNullOrEmpty(userMail))
                {
                    emailSended = Emails.EmailUtils.SendMailTraitementDemande(currentWeb, userMail, demandeTitle);

                    LogManager.LogDebug(traceContext, string.Format("Mail sended to {0} = {1}.", userMail, emailSended));
                }
                else
                    LogManager.LogDebug(traceContext, string.Format("Mail({0}) IsNullOrEmpty.", userLogin));
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("{0} Erreur lors de la notification du traitement la demande '{1}' par email au user '{2}'.", traceContext, demandeTitle, userLogin));
            }
            return emailSended;
        }

        public static bool SendNotificationActionAchevee(SPWeb currentWeb, string traceContext, SPUser user, string actionTitle, string planActionTitle)
        {
            bool emailSended = false;
            string userLogin = string.Empty;
            try
            {
                userLogin = user.LoginName;
                string userMail = user.Email;//UserUtils.GetSPUSerEmail(userLogin);
                if (!string.IsNullOrEmpty(userMail))
                {
                    emailSended = Emails.EmailUtils.SendMailActionAchevee(currentWeb, userMail, planActionTitle, actionTitle);

                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail sended to {0} = {1}.", userMail, emailSended));
                }
                else
                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail({0}) IsNullOrEmpty.",
                                                      userLogin));
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("{0} Erreur lors de la notification de l'achevement de l'action '{1}' par email au user '{2}'.", traceContext, actionTitle, userLogin));
            }
            return emailSended;
        }

        public static bool SendNotificationPlanActionTraite(SPWeb currentWeb, string traceContext, SPUser user, string planActionTitle)
        {
            bool emailSended = false;
            string userLogin = string.Empty;
            try
            {
                userLogin = user.LoginName;
                string userMail = user.Email;//UserUtils.GetSPUSerEmail(userLogin);
                if (!string.IsNullOrEmpty(userMail))
                {
                    emailSended = Emails.EmailUtils.SendMailPlanActionTraite(currentWeb, userMail, planActionTitle);

                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail sended to {0} = {1}.", userMail, emailSended));
                }
                else
                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail({0}) IsNullOrEmpty.",
                                                      userLogin));
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("{0} Erreur lors de la notification de traitement du plan d'actions '{1}' par email au user '{2}'.", traceContext, planActionTitle, userLogin));
            }
            return emailSended;
        }
        public static bool SendNotificationPlanActionEnAttenteCloture(SPWeb currentWeb, string traceContext, SPUser user, string planActionTitle)
        {
            bool emailSended = false;
            string userLogin = string.Empty;
            try
            {
                userLogin = user.LoginName;
                string userMail = user.Email;//UserUtils.GetSPUSerEmail(userLogin);
                if (!string.IsNullOrEmpty(userMail))
                {
                    emailSended = Emails.EmailUtils.SendMailPlanActionEnAttenteCloture(currentWeb, userMail, planActionTitle);

                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail sended to {0} = {1}.", userMail, emailSended));
                }
                else
                    LogManager.LogDebug(traceContext,
                                        string.Format("Mail({0}) IsNullOrEmpty.",
                                                      userLogin));
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("{0} Erreur lors de la notification de l'attente de cloture du plan d'actions '{1}' par email au user '{2}'.", traceContext, planActionTitle, userLogin));
            }
            return emailSended;
        }

        #endregion

        #region Methods Events

        public void OnActionUpdated(SPItemEventProperties properties)
        {
            try
            {
                LogManager.LogDebug("[ActionReceiver][ItemUpdated]", string.Format("Action '{0}' updated.", new object[]{
                        properties.ListItem.Title                                                                                                          
                    }));

                // Get DataContext from page context
                DataContext data = new DataContext(properties.WebUrl);

                // Get the SharePoint list
                EntityList<ActionsTâche> actionsList = data.GetList<ActionsTâche>(SPListItemPlanActionUtility.LIST_ACTIONS);

                // Query items
                ActionsTâche action = (
                    from a in actionsList
                    where a.ID == properties.ListItemId
                    select a).FirstOrDefault();

                // Si la demande est déclarée "achevée"
                if (action.ÉtatDeLaTâche.HasValue && action.ÉtatDeLaTâche.Value == ÉtatDeLaTâche.Terminé)
                {
                    try
                    {
                        SPFieldUserValue responsableField = new SPFieldUserValue(properties.Web, action.PlanDActions.ResponsableID.Value, action.PlanDActions.ResponsableImnName);
                        // alerte responsable PA
                        bool emailSended = SendNotificationActionAchevee(properties.Web, "[ActionReceiver][ItemUpdated]", responsableField.User,
                                                                         action.Titre, action.PlanDActions.Titre);

                        // Mise à jour de l'action
                        action.Achevé = 1.0;

                        // Mise à jour du plan d'actions
                        int nbActionsTermine = 0;
                        foreach (var linkedAction in action.PlanDActions.ActionsTâche)
                        {
                            if (linkedAction.ÉtatDeLaTâche.HasValue && linkedAction.ÉtatDeLaTâche.Value == ÉtatDeLaTâche.Terminé)
                                nbActionsTermine++;
                        }
                        action.PlanDActions.Informations = string.Format(" - {0}/{1} action(s) terminée(s).", nbActionsTermine, action.PlanDActions.ActionsTâche.Count);
                        if (nbActionsTermine == action.PlanDActions.ActionsTâche.Count)
                            action.PlanDActions.Statut = Statut.Traité;

                        // Submit all changes
                        data.SubmitChanges();

                    }
                    catch (Exception ex)
                    {
                        LogManager.LogException(ex, string.Format("[ActionReceiver][ItemUpdated] Erreur lors de la mise à jour de l'action '{0}'", properties.ListItem.Title));
                    }

                }

            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("[ActionReceiver][ItemUpdated] Erreur non gérée lors de la mise à jour de l'action '{0}'", properties.ListTitle));
            }
        }

        public void OnDemandeUpdated(SPItemEventProperties properties)
        {
            try
            {
                //bool stateChanged = (properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT] != properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT]);
                //bool planActionChanged = (properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS] != properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS]);

                //LogManager.LogDebug("[DemandeActionReceiver][ItemUpdated]", string.Format("StateChanged[{0}->{1}]:{2}, PlanActionChanged=[{3}->{4}]:{5}", new object[]{
                //        properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT],
                //        properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_ETAT],
                //        stateChanged, 
                //        properties.BeforeProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS],
                //        properties.AfterProperties[SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS],
                //        planActionChanged                                                                                                                    
                //    }));
                //bool notifyDemandeur = false;

                // Get DataContext from page context
                DataContext data = new DataContext(properties.WebUrl);

                // Get the SharePoint list
                EntityList<DemandesÉlément> demandesList = data.GetList<DemandesÉlément>(SPListItemPlanActionUtility.LIST_DEMANDES);

                // Query items
                DemandesÉlément demande = (from d in demandesList
                                           where d.ID == properties.ListItemId
                                           select d).FirstOrDefault();

                // Si la demande est déclarée "réalisée"|"rejetée"
                if (demande.Etat.HasValue && (demande.Etat.Value == Etat.Traitée || demande.Etat.Value == Etat.Rejetée))
                {
                    // notification mail cloture demande au demandeur
                    string createdByValue =
                        (string)(properties.ListItem[SPListItemPlanActionUtility.FIELD_CREATED_BY] ?? String.Empty);
                    SPFieldUserValue createdByUserValue = new SPFieldUserValue(properties.Web, createdByValue);
                    bool emailSended = SendNotificationClotureDemande(properties.Web, "[DemandeActionReceiver][ItemUpdated]", createdByUserValue.User, demande.Titre, demande.Etat.Value.ToString());

                    // maj date cloture
                    demande.Cloture = DateTime.Now;

                    // Submit all changes
                    data.SubmitChanges();

                    //properties.ListItem[SPListItemPlanActionUtility.FIELD_DEMANDES_CLOTURE] = DateTime.Now;
                    //properties.ListItem.Update();
                }
                else if (demande.Etat.HasValue && demande.Etat.Value == Etat.EnCoursDeTraitement && demande.PlanDActions != null)
                {
                    demande.Etat = Etat.EnCoursDeTraitement;
                    demande.Informations = "Plan d'action attaché.";

                    // Submit all changes
                    data.SubmitChanges();

                    // notification mail traitement au demandeur
                    string createdByValue =
                        (string)(properties.ListItem[SPListItemPlanActionUtility.FIELD_CREATED_BY] ?? String.Empty);
                    SPFieldUserValue createdByUserValue = new SPFieldUserValue(properties.Web, createdByValue);
                    if (createdByUserValue != null && createdByUserValue.User != null)
                        SendNotificationTraitementDemande(properties.Web, "[DemandeActionReceiver][ItemUpdated]", createdByUserValue.User, demande.Titre);
                }
                // - cas 2 -
                // si la demande est déclarée en cours de traitement mais n'a pas de plan d'actions attaché, alors on le crée
                else if (demande.Etat.HasValue && demande.Etat.Value == Etat.EnCoursDeTraitement && demande.PlanDActions == null)
                {
                    try
                    {
                        // Get the SharePoint list
                        EntityList<PlansDActionsÉlément> plansActions =
                            data.GetList<PlansDActionsÉlément>("Plans d'actions");// (SPListItemPlanActionUtility.LIST_PLANS_ACTIONS);

                        EntityList<ProcessusÉlément> processusList =
                            data.GetList<ProcessusÉlément>(SPListItemPlanActionUtility.LIST_PROCESSUS);

                        // Query for customers from London
                        var selectedProcessus = (from processus in processusList
                                                 where processus.ID == demande.Processus.ID
                                                 select processus).FirstOrDefault();

                        // Create the item to be added
                        PlansDActionsÉlément planActions = new PlansDActionsÉlément()
                        {
                            Titre = demande.Titre,
                            Description = demande.Description,
                            Criticité = demande.Criticité,
                            Problématique = demande.Problématique,
                            Processus = selectedProcessus,
                            RésultatAttendu = demande.RésultatAttendu,
                            Statut = Statut.ATraiter,
                            Origine = Origine.Demande,
                            ResponsableID = selectedProcessus.PiloteID,
                            ResponsableImnName = selectedProcessus.PiloteImnName,
                            ResponsableProcessusID = selectedProcessus.PiloteID,
                            ResponsableProcessusImnName = selectedProcessus.PiloteImnName
                        };

                        // Mark the item to be added on the next call of Submit
                        plansActions.InsertOnSubmit(planActions);

                        demande.Informations = demande.Informations + "; Plan d'action créé.";
                        demande.PlanDActions = planActions;

                        // Submit all changes
                        data.SubmitChanges();


                        // notification mail traitement au demandeur
                        string createdByValue =
                            (string)(properties.ListItem[SPListItemPlanActionUtility.FIELD_CREATED_BY] ?? String.Empty);
                        SPFieldUserValue createdByUserValue = new SPFieldUserValue(properties.Web, createdByValue);
                        if (createdByUserValue != null && createdByUserValue.User != null)
                            SendNotificationTraitementDemande(properties.Web, "[DemandeActionReceiver][ItemUpdated]", createdByUserValue.User, demande.Titre);
                    }
                    catch (Exception ex)
                    {
                        LogManager.LogException(ex, string.Format("[DemandeActionReceiver][ItemUpdated] Erreur lors de la création du plan d'actions à partir de la demande '{0}'", properties.ListItem.Title));
                    }

                }
            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("[DemandeActionReceiver][ItemUpdated] Erreur non gérée sur l'ajout d'un item de la liste '{0}'", properties.ListTitle));
            }
        }

        public void OnPlanActionUpdated(SPItemEventProperties properties)
        {
            try
            {
                LogManager.LogDebug("[PlanActionReceiver][ItemUpdated]", string.Format("Plan d'action '{0}' updated.", new object[]{
                        properties.ListItem.Title                                                                                                          
                    }));

                // Get DataContext from page context
                DataContext data = new DataContext(properties.WebUrl);

                // Get the SharePoint list
                EntityList<PlansDActionsÉlément> plansActionsList = data.GetList<PlansDActionsÉlément>(SPListItemPlanActionUtility.LIST_ACTIONS);

                // Query items
                PlansDActionsÉlément planAction = (
                    from a in plansActionsList
                    where a.ID == properties.ListItemId
                    select a).FirstOrDefault();

                // Si le plan est déclarée "traité"
                if (planAction.Statut.HasValue && planAction.Statut.Value == Statut.Traité)
                {
                    try
                    {
                        // alerte responsable PA
                        SPFieldUserValue responsableUserValue = new SPFieldUserValue(properties.Web, planAction.ResponsableID.Value, planAction.ResponsableImnName);
                        if (responsableUserValue != null && responsableUserValue.User != null)
                            SendNotificationPlanActionTraite(properties.Web, "[PlanActionReceiver][ItemUpdated]", responsableUserValue.User, planAction.Titre);

                        // Mise à jour du plan d'actions

                        // Submit all changes
                        //data.SubmitChanges();

                    }
                    catch (Exception ex)
                    {
                        LogManager.LogException(ex, string.Format("[PlanActionReceiver][ItemUpdated] Erreur lors de la mise à jour du plan d'action '{0}'", properties.ListItem.Title));
                    }

                }
                else if (planAction.Statut.HasValue && planAction.Statut.Value == Statut.EnAttenteDeClôture)
                {
                    try
                    {
                        // alerte responsable PA
                        SPFieldUserValue responsableUserValue = new SPFieldUserValue(properties.Web, planAction.ResponsableID.Value, planAction.ResponsableImnName);
                        if (responsableUserValue != null && responsableUserValue.User != null)
                            SendNotificationPlanActionTraite(properties.Web, "[PlanActionReceiver][ItemUpdated]", responsableUserValue.User, planAction.Titre);

                        // Mise à jour du plan d'actions

                        // Submit all changes
                        //data.SubmitChanges();

                    }
                    catch (Exception ex)
                    {
                        LogManager.LogException(ex, string.Format("[PlanActionReceiver][ItemUpdated] Erreur lors de la mise à jour du plan d'action '{0}'", properties.ListItem.Title));
                    }

                }
                else if (planAction.Statut.HasValue && planAction.Statut.Value == Statut.Clôturé)
                {
                    try
                    {
                        // Mise à jour des demandes attachées au plan d'actions
                        foreach (var demande in planAction.DemandesÉlément.AsEnumerable())
                        {
                            demande.Etat = Etat.Traitée;
                            demande.Cloture = DateTime.Now;
                        } 

                        // Submit all changes
                        data.SubmitChanges();

                    }
                    catch (Exception ex)
                    {
                        LogManager.LogException(ex, string.Format("[PlanActionReceiver][ItemUpdated] Erreur lors de la mise à jour des demandes du plan d'action '{0}'", properties.ListItem.Title));
                    }

                }

            }
            catch (Exception ex)
            {
                LogManager.LogException(ex, string.Format("[PlanActionReceiver][ItemUpdated] Erreur non gérée lors de la mise à jour du plan d'action '{0}'", properties.ListTitle));
            }
        }

        #endregion

        #region Methods Security
        public void ApplySecurityOnDemande(string traceContext, SPItemEventProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(
                delegate
                {
                    using (var currentSite = new SPSite(properties.WebUrl))
                    {
                        bool allowUnsafeUpdatesOldValue = currentSite.AllowUnsafeUpdates;
                        currentSite.AllowUnsafeUpdates = true;
                        using (var currentWeb = currentSite.OpenWeb())
                        {
                            try
                            {
                                SPList currentList = currentWeb.Lists[properties.ListTitle];
                                SPListItem currentListItem = currentList.GetItemById(properties.ListItemId);

                                // on casse l'héritage des droits
                                currentListItem.ResetRoleInheritance();
                                currentListItem.BreakRoleInheritance(false);

                                // demandeur en écriture
                                try
                                {
                                    SPUser createdByUser =
                                        UserUtils.GetSPListItemUsers(currentWeb, currentListItem,
                                                                     SPListItemPlanActionUtility.FIELD_CREATED_BY).First
                                            ();
                                    GroupManager.AssignRoleToGroupOrUserForObject(createdByUser, currentListItem,
                                                                                  SecurityConstants.
                                                                                      ROLE_DEFINITION_CONTRIBUTE_NO_DELETE,
                                                                                  currentWeb);
                                }
                                catch
                                {
                                }
                                // direction en écriture
                                try
                                {
                                    SPGroup groupDirection = GroupManager.GetGroup(currentWeb.Groups,
                                                                                   SecurityConstants.GROUP_DIRECTION);
                                    GroupManager.AssignRoleToGroupOrUserForObject(groupDirection, currentListItem,
                                                                                  SecurityConstants.
                                                                                      ROLE_DEFINITION_CONTRIBUTE_NO_DELETE,
                                                                                  currentWeb);
                                }
                                catch
                                {
                                }
                                // Processus:
                                try
                                {
                                    ProcessusÉlément currentProcessus =
                                        SPListItemPlanActionUtility.GetDemandeByID(properties.WebUrl, currentListItem.ID)
                                            .Processus;

                                    // responsable processus en écriture
                                    //SPPrincipal responsableUser = UserUtils.GetSPPrincipal(properties.Web, currentProcessus.PiloteImnName);
                                    SPFieldUserValue responsableUser = new SPFieldUserValue(properties.Web, currentProcessus.PiloteID.Value, currentProcessus.PiloteImnName);
                                    GroupManager.AssignRoleToGroupOrUserForObject(responsableUser.User, currentListItem,
                                                                              SecurityConstants.
                                                                                  ROLE_DEFINITION_CONTRIBUTE_NO_DELETE,
                                                                              currentWeb);

                                    // Collaborateurs du processus en lecture
                                    for (int i = 0; i < currentProcessus.CollaborateursID.Count; i++)
                                    {
                                        SPFieldUserValue collaborateurUser = new SPFieldUserValue(properties.Web, currentProcessus.CollaborateursID[i].Value, currentProcessus.CollaborateursImnName[i]);
                                        GroupManager.AssignRoleToGroupOrUserForObject(collaborateurUser.User, currentListItem,
                                                                                      SecurityConstants.
                                                                                          ROLE_DEFINITION_READ,
                                                                                      currentWeb);
                                    }
                                }
                                catch
                                {
                                }
                            }
                            catch (Exception ex)
                            {
                                LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits à l'item '{1}'.", traceContext, properties.ListItem.Title));
                            }

                        }//end using web
                        currentSite.AllowUnsafeUpdates = allowUnsafeUpdatesOldValue;
                    }//end using site
                });//end delegate
        }
        public void ApplySecurityOnPlanActions(string traceContext, SPItemEventProperties properties)
        {
            SPSecurity.RunWithElevatedPrivileges(
                delegate
                {
                    using (var currentSite = new SPSite(properties.WebUrl))
                    {
                        bool allowUnsafeUpdatesOldValue = currentSite.AllowUnsafeUpdates;
                        currentSite.AllowUnsafeUpdates = true;
                        using (var currentWeb = currentSite.OpenWeb())
                        {
                            try
                            {
                                SPList currentList = currentWeb.Lists[properties.ListTitle];
                                SPListItem currentListItem = currentList.GetItemById(properties.ListItemId);

                                // on casse l'héritage des droits
                                currentListItem.ResetRoleInheritance();
                                currentListItem.BreakRoleInheritance(false);

                                // Get DataContext from page context
                                DataContext data = new DataContext(properties.WebUrl);

                                // Get the SharePoint list
                                EntityList<PlansDActionsÉlément> plansActionsList = data.GetList<PlansDActionsÉlément>(SPListItemPlanActionUtility.LIST_ACTIONS);

                                // Query items
                                PlansDActionsÉlément planAction = (
                                    from a in plansActionsList
                                    where a.ID == properties.ListItemId
                                    select a).FirstOrDefault();

                                // créateur en écriture
                                try
                                {
                                    LogManager.LogDebug(traceContext, string.Format("Affectation des droits du créateur de l'item '{0}'.", properties.ListItem.Title));
                                    SPFieldUserValue createdByUser = new SPFieldUserValue(properties.Web, currentListItem[SPListItemPlanActionUtility.FIELD_CREATED_BY].ToString());
                                    //SPUser createdByUser =
                                    //    UserUtils.GetSPListItemUsers(currentWeb, currentListItem,
                                    //                                 SPListItemPlanActionUtility.FIELD_CREATED_BY).First
                                    //        ();
                                    GroupManager.AssignRoleToGroupOrUserForObject(createdByUser.User, currentListItem,
                                                                                  SecurityConstants.
                                                                                      ROLE_DEFINITION_CONTRIBUTE_NO_DELETE,
                                                                                  currentWeb);
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits du créateur de l'item '{1}'.", traceContext, properties.ListItem.Title));
                                }

                                // responsable PA en écriture
                                try
                                {
                                    LogManager.LogDebug(traceContext, string.Format("Affectation des droits du responsable PA de l'item '{0}'.", properties.ListItem.Title));
                                    SPFieldUserValue responsablePaUser = new SPFieldUserValue(properties.Web, currentListItem[SPListItemPlanActionUtility.FIELD_PLANS_RESPONSABLE].ToString());
                                    GroupManager.AssignRoleToGroupOrUserForObject(responsablePaUser.User, currentListItem,
                                                                                  SecurityConstants.
                                                                                      ROLE_DEFINITION_CONTRIBUTE_NO_DELETE,
                                                                                  currentWeb);
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits du responsable PA de l'item '{1}'.", traceContext, properties.ListItem.Title));
                                }
                                // direction en écriture
                                try
                                {
                                    LogManager.LogDebug(traceContext, string.Format("Affectation des droits du groupe Direction de l'item '{0}'.", properties.ListItem.Title));
                                    SPGroup groupDirection = GroupManager.GetGroup(currentWeb.Groups,
                                                                                   SecurityConstants.GROUP_DIRECTION);
                                    GroupManager.AssignRoleToGroupOrUserForObject(groupDirection, currentListItem,
                                                                                  SecurityConstants.
                                                                                      ROLE_DEFINITION_CONTRIBUTE_NO_DELETE,
                                                                                  currentWeb);
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits du groupe Direction à l'item '{1}'.", traceContext, properties.ListItem.Title));
                                }
                                // Processus:
                                try
                                {
                                    LogManager.LogDebug(traceContext, string.Format("Affectation des droits du responsable de processus de l'item '{0}'.", properties.ListItem.Title));
                                    // responsable processus en écriture
                                    SPFieldUserValue responsableUser = new SPFieldUserValue(properties.Web, currentListItem[SPListItemPlanActionUtility.FIELD_PLANS_RESPONSABLE_PROCESSUS].ToString());
                                    GroupManager.AssignRoleToGroupOrUserForObject(responsableUser.User, currentListItem,
                                                                                  SecurityConstants.
                                                                                      ROLE_DEFINITION_CONTRIBUTE_NO_DELETE,
                                                                                  currentWeb);
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits du responsable du processus à l'item '{1}'.", traceContext, properties.ListItem.Title));
                                }
                                try
                                {
                                    LogManager.LogDebug(traceContext, string.Format("Affectation des droits des collaborateurs du processus de l'item '{0}'.", properties.ListItem.Title));
                                    // Collaborateurs du processus en lecture
                                    for (int i = 0; i < planAction.Processus.CollaborateursID.Count; i++)
                                    {
                                        SPFieldUserValue collaborateurUser = new SPFieldUserValue(properties.Web, planAction.Processus.CollaborateursID[i].Value, planAction.Processus.CollaborateursImnName[i]);
                                        GroupManager.AssignRoleToGroupOrUserForObject(collaborateurUser.User, currentListItem,
                                                                                      SecurityConstants.
                                                                                          ROLE_DEFINITION_READ,
                                                                                      currentWeb);
                                    }
                                }
                                catch (Exception ex)
                                {
                                    LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits des collaborateurs du processus à l'item '{1}'.", traceContext, properties.ListItem.Title));
                                }

                                try
                                {
                                    // Demandeurs initiaux en lecture
                                    LogManager.LogDebug(traceContext, string.Format("Affectation des droits des demandeurs initiaux de l'item '{0}'.", properties.ListItem.Title));

                                    // on récupère les demandes liées au plan 
                                    SPQuery query = new SPQuery();
                                    StringBuilder queryBuilder = new StringBuilder();
                                    queryBuilder
                                        .AppendLine("<Where>")
                                        .AppendLine("<Eq>")
                                        .AppendFormat("<FieldRef Name='{0}' LookupId='TRUE'/>", SPListItemPlanActionUtility.FIELD_DEMANDES_PLAN_ACTIONS)
                                        .AppendFormat("<Value Type='Lookup'>{0}</Value>", properties.ListItemId)
                                        .AppendLine("</Eq>")
                                        .AppendLine("</Where>");
                                    query.Query = queryBuilder.ToString();
                                    SPList demandesList = currentWeb.Lists[SPListItemPlanActionUtility.LIST_DEMANDES];
                                    SPListItemCollection demandes = demandesList.GetItems(query);

                                    foreach (SPListItem demande in demandes)
                                    {
                                        // en récupère le créateur de la demande
                                        SPFieldUserValue demandeur = new SPFieldUserValue(currentWeb, demande[SPListItemPlanActionUtility.FIELD_CREATED_BY].ToString());
                                        // on lui donne les droits sur le plan d'actions courant
                                        GroupManager.AssignRoleToGroupOrUserForObject(demandeur.User, currentListItem, SecurityConstants.ROLE_DEFINITION_READ, currentWeb);
                                    }
                                }
                                catch(Exception ex)
                                {
                                    LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits des demandeurs initiaux à l'item '{1}'.", traceContext, properties.ListItem.Title));
                                }
                            }
                            catch (Exception ex)
                            {
                                LogManager.LogException(ex, string.Format("{0} Erreur de l'affectation des droits à l'item '{1}'.", traceContext, properties.ListItem.Title));
                            }


                        }//end using web
                        currentSite.AllowUnsafeUpdates = allowUnsafeUpdatesOldValue;
                    }//end using site
                });//end delegate
        }

        #endregion
    }
}
